package org.example.erat.log.observer;

import org.example.erat.log.core.LogObserver;
import org.example.erat.log.core.LoggerSingleton;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 文件日志观察者
 * 将日志写入文件
 */
@Component
public class FileLogObserver implements LogObserver {
    
    private final String logDir;
    private final String systemLogPath;
    private final String errorLogPath;
    private final String operationLogPath;
    private final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    private final SimpleDateFormat operationDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    
    // 日志统计
    private final ConcurrentHashMap<String, AtomicInteger> logCounters = new ConcurrentHashMap<>();
    private final AtomicInteger totalLogCount = new AtomicInteger(0);
    private final AtomicInteger errorLogCount = new AtomicInteger(0);
    private final AtomicInteger warnLogCount = new AtomicInteger(0);
    private final AtomicInteger infoLogCount = new AtomicInteger(0);
    private final AtomicInteger operationLogCount = new AtomicInteger(0);
    
    /**
     * 构造函数
     */
    public FileLogObserver() {
        // 创建日志目录
        this.logDir = "logs";
        File dir = new File(logDir);
        if (!dir.exists()) {
            boolean created = dir.mkdirs();
            if (!created) {
                System.err.println("创建日志目录失败: " + logDir);
            }
        }
        
        // 设置日志文件路径
        this.systemLogPath = logDir + File.separator + "system.log";
        this.errorLogPath = logDir + File.separator + "error.log";
        this.operationLogPath = logDir + File.separator + "operation.log";
        
        // 注册到日志单例
        LoggerSingleton.getInstance().addObserver(this);
        
        // 记录启动日志
        writeToFile(systemLogPath, formatSystemLogEntry("INFO", "文件日志观察者初始化完成"));
        writeToFile(operationLogPath, formatOperationLogEntry("系统启动，文件日志观察者初始化完成"));
    }
    
    @Override
    public void update(String level, String message) {
        // 更新日志计数
        totalLogCount.incrementAndGet();
        logCounters.computeIfAbsent(level, k -> new AtomicInteger(0)).incrementAndGet();
        
        // 处理不同级别的日志
        switch (level) {
            case "ERROR":
                errorLogCount.incrementAndGet();
                writeToFile(errorLogPath, formatSystemLogEntry(level, message));
                writeToFile(systemLogPath, formatSystemLogEntry(level, message));
                
                // 严重错误也记录到操作日志
                if (isOperationLog(message)) {
                    operationLogCount.incrementAndGet();
                    writeToFile(operationLogPath, formatOperationLogEntry("错误: " + message));
                }
                break;
                
            case "WARN":
                warnLogCount.incrementAndGet();
                writeToFile(systemLogPath, formatSystemLogEntry(level, message));
                
                // 文件名不合规或学生不在名单中的警告记录到操作日志
                if (isOperationLog(message)) {
                    operationLogCount.incrementAndGet();
                    writeToFile(operationLogPath, formatOperationLogEntry("警告: " + message));
                }
                break;
                
            case "INFO":
                infoLogCount.incrementAndGet();
                writeToFile(systemLogPath, formatSystemLogEntry(level, message));
                
                // 操作日志记录到专门的文件
                if (isOperationLog(message)) {
                    operationLogCount.incrementAndGet();
                    writeToFile(operationLogPath, formatOperationLogEntry(message));
                }
                break;
                
            default:
                writeToFile(systemLogPath, formatSystemLogEntry(level, message));
                break;
        }
    }
    
    /**
     * 判断是否是操作日志
     * @param message 日志消息
     * @return 是否是操作日志
     */
    private boolean isOperationLog(String message) {
        return message.startsWith("操作:") ||
               message.startsWith("【") ||
               message.contains("成功") ||
               message.contains("完成") ||
               message.contains("导入") ||
               message.contains("分析") ||
               message.contains("文件名不合规") ||
               message.contains("学生不在名单中") ||
               message.contains("不支持的文件类型");
    }
    
    /**
     * 格式化系统日志条目
     * @param level 日志级别
     * @param message 日志消息
     * @return 格式化后的日志条目
     */
    private String formatSystemLogEntry(String level, String message) {
        String timestamp = dateFormat.format(new Date());
        return String.format("[%s] [%s] %s", timestamp, level, message);
    }
    
    /**
     * 格式化操作日志条目（简化格式，便于查看）
     * @param message 日志消息
     * @return 格式化后的日志条目
     */
    private String formatOperationLogEntry(String message) {
        String timestamp = operationDateFormat.format(new Date());
        return String.format("%s - %s", timestamp, message);
    }
    
    /**
     * 写入日志到文件
     * @param filePath 文件路径
     * @param logEntry 日志条目
     */
    private void writeToFile(String filePath, String logEntry) {
        try (FileWriter fw = new FileWriter(filePath, true);
             PrintWriter pw = new PrintWriter(fw)) {
            
            pw.println(logEntry);
            
        } catch (IOException e) {
            System.err.println("写入日志文件失败: " + filePath + ", " + e.getMessage());
        }
    }
    
    /**
     * 获取日志统计信息
     * @return 日志统计信息
     */
    public String getLogStats() {
        return String.format("日志统计 - 总数: %d, 信息: %d, 警告: %d, 错误: %d, 操作: %d",
                totalLogCount.get(), infoLogCount.get(), warnLogCount.get(),
                errorLogCount.get(), operationLogCount.get());
    }
}
